package org.dromara.utils;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 汉语转换成拼音类
 *
 * @author yangxin_ryan
 */
public class HanyuPinyinUtil {

    private static final Log LOG = LogFactory.getLog(HanyuPinyinUtil.class);

    /**
     * 将文字转为汉语拼音
     *
     * @param chineseLanguage 要转成拼音的中文
     * @return 转换后的拼音字符串，每个拼音之间用空格隔开
     */
    public String toHanyuPinyin(String chineseLanguage) {
        if (StringUtils.isEmpty(chineseLanguage)){
            return null;
        }
        StringBuilder pinyinBuilder = new StringBuilder();
        HanyuPinyinOutputFormat format = getDefaultFormat(HanyuPinyinCaseType.LOWERCASE, HanyuPinyinToneType.WITHOUT_TONE, HanyuPinyinVCharType.WITH_V);
        char[] chars = chineseLanguage.trim().toCharArray();

        for (char c : chars) {
            if (isChineseCharacter(c)) {
                try {
                    pinyinBuilder.append(PinyinHelper.toHanyuPinyinStringArray(c, format)[0]).append(" ");
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    LOG.info("字符不能转成汉语拼音");
                }
            } else {
                pinyinBuilder.append(c);
            }
        }

        return pinyinBuilder.toString();
    }

    /**
     * 转换拼音字符串中第一个为大写
     *
     * @param chineseLanguage 中文输入
     * @return 转换后的拼音首字母大写的字符串
     */
    public String getFirstLettersUp(String chineseLanguage) {
        return getFirstLetters(chineseLanguage, HanyuPinyinCaseType.UPPERCASE);
    }

    /**
     * 转换拼音字符串第一个为小写
     *
     * @param chineseLanguage 中文输入
     * @return 转换后的拼音首字母小写的字符串
     */
    public String getFirstLettersLo(String chineseLanguage) {
        return getFirstLetters(chineseLanguage, HanyuPinyinCaseType.LOWERCASE);
    }

    /**
     * 获取拼音首字母字符串
     *
     * @param chineseLanguage 中文输入
     * @param caseType        大小写类型
     * @return 拼音首字母字符串
     */
    public String getFirstLetters(String chineseLanguage, HanyuPinyinCaseType caseType) {
        StringBuilder pinyinBuilder = new StringBuilder();
        HanyuPinyinOutputFormat format = getDefaultFormat(caseType, HanyuPinyinToneType.WITHOUT_TONE, null);
        char[] chars = chineseLanguage.trim().toCharArray();

        for (char c : chars) {
            String charStr = String.valueOf(c);
            if (isChineseCharacter(c)) {
                try {
                    pinyinBuilder.append(PinyinHelper.toHanyuPinyinStringArray(c, format)[0].substring(0, 1));
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    LOG.error("字符不能转成汉语拼音");
                }
            } else if (charStr.matches("[0-9]+")) {
                pinyinBuilder.append(c);
            } else if (charStr.matches("[a-zA-Z]+")) {
                pinyinBuilder.append(c);
            } else {
                pinyinBuilder.append(c);
            }
        }

        return pinyinBuilder.toString();
    }

    /**
     * 获取拼音字符串
     *
     * @param chineseLanguage 中文输入
     * @return 转换后的拼音字符串
     */
    public String getPinyinString(String chineseLanguage) {
        StringBuilder pinyinBuilder = new StringBuilder();
        HanyuPinyinOutputFormat format = getDefaultFormat(HanyuPinyinCaseType.LOWERCASE, HanyuPinyinToneType.WITHOUT_TONE, null);
        char[] chars = chineseLanguage.trim().toCharArray();

        for (char c : chars) {
            String charStr = String.valueOf(c);
            if (isChineseCharacter(c)) {
                try {
                    pinyinBuilder.append(PinyinHelper.toHanyuPinyinStringArray(c, format)[0]);
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    LOG.error("字符不能转成汉语拼音");
                }
            } else if (charStr.matches("[0-9]+")) {
                pinyinBuilder.append(c);
            } else if (charStr.matches("[a-zA-Z]+")) {
                pinyinBuilder.append(c);
            }
        }

        return pinyinBuilder.toString();
    }

    /**
     * 取第一个汉字的第一个字符
     *
     * @param chineseLanguage 中文输入
     * @return 第一个汉字的拼音首字母或其他字符
     */
    public String getFirstLetter(String chineseLanguage) {
        StringBuilder pinyinBuilder = new StringBuilder();
        HanyuPinyinOutputFormat format = getDefaultFormat(HanyuPinyinCaseType.UPPERCASE, HanyuPinyinToneType.WITHOUT_TONE, null);
        char[] chars = chineseLanguage.trim().toCharArray();

        if (chars.length > 0) {
            String charStr = String.valueOf(chars[0]);
            if (isChineseCharacter(chars[0])) {
                try {
                    pinyinBuilder.append(PinyinHelper.toHanyuPinyinStringArray(chars[0], format)[0].substring(0, 1));
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    LOG.error("字符不能转成汉语拼音");
                }
            } else if (charStr.matches("[0-9]+")) {
                pinyinBuilder.append(chars[0]);
            } else if (charStr.matches("[a-zA-Z]+")) {
                pinyinBuilder.append(chars[0]);
            }
        }

        return pinyinBuilder.toString();
    }

    /**
     * 判断字符是否为中文字符
     *
     * @param c 字符
     * @return 如果是中文字符返回 true，否则返回 false
     */
    private boolean isChineseCharacter(char c) {
        return String.valueOf(c).matches("[\u4e00-\u9fa5]+");
    }

    /**
     * 获取默认的拼音输出格式
     *
     * @param caseType  大小写类型
     * @param toneType  声调类型
     * @param vCharType V 字符类型
     * @return 配置好的拼音输出格式
     */
    private HanyuPinyinOutputFormat getDefaultFormat(HanyuPinyinCaseType caseType, HanyuPinyinToneType toneType, HanyuPinyinVCharType vCharType) {
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setCaseType(caseType);
        format.setToneType(toneType);
        if (vCharType != null) {
            format.setVCharType(vCharType);
        }
        return format;
    }

    /**
     * 测试程序入口
     *
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        HanyuPinyinUtil hanyuPinyinUtil = new HanyuPinyinUtil();
        System.out.println(hanyuPinyinUtil.toHanyuPinyin("测试汉语字符串"));
    }
}
